﻿/*
 * Created by SharpDevelop.
 * User: lebeda
 * Date: 17.2.2014
 * Time: 7:31
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

namespace simpleExplorer.menuProviderImpl
{
    /// <summary>
    /// Description of NotesMenuProvider.
    /// </summary>
    public class NotesMenuProvider: AbstractMenuProvider, MenuItemProvider
    {
        
        Dictionary<string, MenuItem> hookIndex = new Dictionary<string, MenuItem>();
        
        public NotesMenuProvider(MenuItem aMenuItem)
        {
            this.SelfMenuItem = aMenuItem;
            string path = Regex.Replace(aMenuItem.cmd, @"\\$", "");
            
            
            loadHooks(path);
            
            buildCustomMenus(path);
            buildDirMenu(path);
            buildFilesMenu(path);
        }

        private void buildDirMenu(string path)
        {
            string[] filePaths = Directory.GetDirectories(path);
            Array.Sort(filePaths);
            foreach (string file in filePaths) {
                string caption = Regex.Replace(file, ".*\\\\", "> ");
                MenuItem menuItem = new MenuItem(caption, ItemTarget.menu, ItemType.filesystemMenuProvider, file, "", 
                                                 Path.GetDirectoryName(file), SelfMenuItem);
                
                if (!checkHooks(file, menuItem)) {                                        
                    menuIndex.Add(caption, menuItem);
                }
            }
        }
        
        bool checkHooks(string file, MenuItem menuItem)
        {
            bool result = false;
            foreach (string pattern in hookIndex.Keys) {
                string name = Path.GetFileName(file);
                if (file.Contains(pattern)) {
                    result = true;
                    
                    // include menu
                    MenuItem hookMenuItem = hookIndex[pattern];
                    Tools.expandMacros(hookMenuItem, menuItem);
                    MenuItemProvider inMenu = Tools.menuProviderFactory(hookMenuItem);
                    foreach (MenuItem lMenuItem in inMenu.GetMenuItemList(null)) {
                        Tools.expandMacros(lMenuItem, menuItem);
                        menuIndex.Add(lMenuItem.caption, lMenuItem);
                    }
                }
            }
            return result;
        }

        private void buildFilesMenu(string path)
        {
//            string[] filePaths = Directory.GetFiles(path);
            
            var filePaths = new DirectoryInfo(path).GetFiles()
                                                  .OrderByDescending(f => f.LastWriteTime)
                                                  .ToList();
            
//             sort by date
//            Array.Sort(filePaths);
            
            foreach (FileInfo fileInfo in filePaths) {
				var file = fileInfo.FullName;
				
				string caption = Regex.Replace(file, ".*\\\\", "");
                caption = Regex.Replace(caption, ".lnk$", "", RegexOptions.IgnoreCase);
            
				// get txt notes captions                
                if (caption.EndsWith(".txt", StringComparison.OrdinalIgnoreCase)) {
                	using (StreamReader reader = new StreamReader(file, Encoding.Default)) {
					    caption = reader.ReadLine();
					    caption += " (" + fileInfo.LastWriteTime + ")";
					}
                }
                
                MenuItem menuItem = new MenuItem(caption, ItemTarget.item, ItemType.execItem, file, "", 
                                                 Path.GetDirectoryName(file), SelfMenuItem);
                
                
                if (!checkHooks(file, menuItem)) {                    
                    menuIndex[caption] = menuItem;
                }
            }
        }

        private void buildCustomMenus(string path)
        {
            string[] filePaths = Directory.GetFiles(path, "*.xmenu");
            Array.Sort(filePaths);
            foreach (string file in filePaths) {
                string caption = Regex.Replace(file, ".*\\\\", "");
                MenuItem menuItem = new MenuItem(caption, ItemTarget.include, ItemType.xmlMenuProvider, file, "", 
                                                 Path.GetDirectoryName(file), SelfMenuItem);
                MenuItemProvider inMenu = Tools.menuProviderFactory(menuItem);
                foreach (MenuItem lMenuItem in inMenu.GetMenuItemList(null)) {
                    menuIndex.Add(lMenuItem.caption, lMenuItem);
                }
            }
        }

        private void loadHooks(string path)
        {
            List<FsHookItem> fsHookList = new List<FsHookItem>();
            List<string> hookPaths = new List<string>();
            hookPaths.AddRange(Directory.GetFiles(path, "*.xhook"));
            hookPaths.AddRange(Directory.GetFiles(Tools.configDirName(), "*.xhook"));
            foreach (string hookPath in hookPaths) {
                fsHookList.AddRange(DeserializeListFromXML(hookPath));
            }
            foreach (FsHookItem fsHook in fsHookList) {
                hookIndex[fsHook.pattern] = fsHook.menuItem;
            }
        }
        
        public override List<MenuItem> GetMenuItemList(string filter) {
            List<MenuItem> result = new List<MenuItem>(menuIndex.Count);
            
            foreach (MenuItem menuItem in menuIndex.Values) {
                string caption = menuItem.caption;
                if (!String.IsNullOrWhiteSpace(filter)) {
                    string smallCaption = caption.ToLower();
                    string smallFind = filter.ToLower();
                    if (smallCaption.Contains(smallFind)) {
                        result.Add(menuItem);
                    }
                } else {
                    result.Add(menuItem);
                }
            }
            
            return result;
        }
        
        // only for test
        //        static public void SerializeListToXML(List<FsHookItem> menuItemList)
        //        {
        //            XmlSerializer serializer = new XmlSerializer(typeof(List<FsHookItem>));
        //            TextWriter textWriter = new StreamWriter(@"C:\inbox\hookItemList.xml");
        //            serializer.Serialize(textWriter, menuItemList);
        //            textWriter.Close();
        //        }

        static List<FsHookItem> DeserializeListFromXML(string hookPath)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(List<FsHookItem>));
            TextReader textReader = new StreamReader(hookPath);
            List<FsHookItem> result;
            result = (List<FsHookItem>)deserializer.Deserialize(textReader);
            textReader.Close();
            return result;
        }

    }
}
